<template>
  <div class="page-transfer">

    <div class="transfer-tips">
      <span>GasPrice：{{gasPrice}}</span>
      <span>GasLimit：{{gasLimit}}</span>
    </div>

    <el-form ref="form" :model="transferInfo" label-width="100px">
      <el-form-item label="来源地址">
        <el-select v-model="transferInfo.from_address" placeholder="请选择from地址" clearable  style="width:100%">
          <el-option v-for="(item,index) in users" :key="item.id" :label="item.address" :value="item.address">
            <span style="float: left">{{ item.username }}</span>
            <span style="float: right; color: #8492a6; font-size: 13px">{{ item.address }}</span>
          </el-option>
        </el-select>
      </el-form-item>

      <el-form-item label="目标地址">
        <el-input v-model="transferInfo.to_address" placeholder="请输入转账到对方的地址"></el-input>
      </el-form-item>

      <el-form-item label="数额(ETH)">
        <div class="inline-form-items">
          <el-input v-model="transferInfo.amount" placeholder="请输入转账数额" class="money-input"></el-input>
          <div class="text">当前账户余额：{{transferInfo.balance}}</div>
        </div>
      </el-form-item>

      <el-form-item label="手续费">
        <el-slider v-model="transferInfo.feePercent" :min="2" :max="200" :format-tooltip="feeTooltip"></el-slider>
      </el-form-item>

      <el-form-item label="备注信息">
        <el-input type="textarea" v-model="transferInfo.extraData" placeholder="extraData"></el-input>
      </el-form-item>

      <el-form-item label="结算">
        <h3>{{settlementText}}</h3>
      </el-form-item>

      <el-form-item style="text-align: right">
        <el-button @click="resetForm">重置表单</el-button>
        <el-button type="primary" @click="prepareTransaction">转账</el-button>
      </el-form-item>
    </el-form>

    <el-dialog
        title="请输入密码"
        :visible.sync="dialogVisible.transaction">
      <div class="create-infos">
        <el-input v-model="transferInfo.password" placeholder="密码" type="password">
          <template slot="prepend">账户密码</template>
        </el-input>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible.transaction = false">取消</el-button>
        <el-button type="danger" @click="sendTransaction">确认转账</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
  import Vue from 'vue'
  import {getLowDB} from "../assets/js/util"
  let db = getLowDB()

  export default {
    data () {
      return {
        dialogVisible: {
          transaction: false
        },
        users: [],
        transferInfo: {
          from_address: '',
          to_address: '',
          amount: 0,
          feePercent: 100,
          extraData: '',
          // user infos
          balance: NaN,
          keystore: {},
          password: ''
        },
        gasPrice: NaN,
        gasLimit: 200000
      }
    },
    watch: {
      'transferInfo.from_address': function () {
        let address = this.transferInfo.from_address

        this.updateBalance(address)
        this.users.forEach(item => {
          if (item.address === address) {
            this.transferInfo.keystore = item.keystore
          }
        })

      }
    },
    computed: {
      // 计算实际手续费用（ether单位）
      fee () {
        if (this.selectedGasPrice) {
          let fee = this.selectedGasPrice * this.gasLimit
          // Pass numbers as strings or BigNumber objects to avoid precision errors.
          return this.$web3.utils.fromWei(fee.toString(), 'ether')
        }
      },
      // 计算交易费 = gasPrice * gasUsed（wei单位）
      selectedGasPrice () {
        if (this.gasPrice) {
          let gasUsed = this.transferInfo.feePercent / 100;
          return Math.ceil(this.gasPrice * gasUsed)
        }
      },
      // 结算文本（直接相加不精确，应该转换成wei相加再转换成ether）
      settlementText () {
        let amount = Number(this.transferInfo.amount) || 0
        let fee = Number(this.fee)
        let result = amount+fee

        return `${amount} + ${fee}(手续费) = ${result} ETH`
      }
    },
    mounted () {
      // from_address选中第一条
      // this.reloadUsers()
      // this.transferInfo.from_address = this.users[0].address
    },
    activated() {
      this.reloadUsers()
      this.updateGasPrice()

       // update gasLimit
      this.$web3.eth.getBlock("latest").then(data => {
        this.gasLimit = data.gasLimit
      });

      console.log('交易记录列表', db.get('trans_logs').value())
    },
    methods: {
      // 刷新用户列表
      reloadUsers () {
        let self = this
        let users = this.users

        this.users = db.get('users').value()

        // 将金额单位Wei转换成Eth
        function _toEthVal (val){
          return self.$web3.utils.fromWei(val, 'ether');
        }

        // 获取余额
        function _getBalance(item) {
          self.$web3.eth.getBalance(item.address).then(data => {
            Vue.set(item, 'balance', _toEthVal(data))
          })
        }

        users.forEach(item => {
          _getBalance(item)
        })

        // 让Vue数组强制更新
        users = users.slice()

        // console.log('reloadUsers', this.users)
      },
      // 更新账户余额
      updateBalance (address) {
        if (address) {
          this.$web3.eth.getBalance(address).then(data => {
            Vue.set(this.transferInfo, 'balance', this.$web3.utils.fromWei(data, 'ether'))
          })
        } else {
          Vue.set(this.transferInfo, 'balance', NaN)
        }
      },
      // 更新Gas价格
      updateGasPrice () {
        this.$web3.eth.getGasPrice().then(data => {
          this.gasPrice = data
        })
      },
      // 检查交易信息
      prepareTransaction () {
        let transferInfo = this.transferInfo

        if (transferInfo.from_address.length <= 0 || transferInfo.to_address <= 0) {
          this.$message.error('交易地址不能为空')
          return
        }

        if (transferInfo.amount > transferInfo.balance) {
          this.$message.error('余额不足')
          return
        }

        // 显示密码弹框
        this.transferInfo.password = ''
        this.dialogVisible.transaction = true
      },
      // 正式转账流程
      sendTransaction () {
        let self = this
        let transferInfo = this.transferInfo

        if (transferInfo.password.length <= 0) {
          this.$message.error('请输入密码')
          return
        }

        // 交易数量
        let value = this.$web3.utils.toWei(transferInfo.amount.toString(), 'ether')
        let account = null

        try {
          // 用密码和address来获取私钥
          account = this.$web3.eth.accounts.decrypt(JSON.stringify(transferInfo.keystore), transferInfo.password)
        } catch (e) {
          console.log('钱包解密失败', e)
          this.$message.error('钱包解密失败，可能是密码错误')
          return
        }

        try {
          // 用私钥签名交易数据
          this.$web3.eth.accounts.signTransaction({
            to: transferInfo.to_address,
            value: value,
            gas: this.gasLimit,
            gasPrice: this.selectedGasPrice,
            data: this.extraData
          }, account.privateKey).then(hex => {
            console.log('签名成功！', hex)
            // 发起交易
            return this.$web3.eth.sendSignedTransaction(hex.rawTransaction)
          }).then(data => {
            console.log('交易发送完成！',JSON.stringify(data))

            let transactionHash = data.transactionHash
            let blockHash = data.blockHash
            // 根据transactionHash查询交易信息
            this.$web3.eth.getTransaction(transactionHash).then(receiptData => {
              console.log(`查询transactionHash ${transactionHash} 的交易信息结果`, JSON.stringify(receiptData))
              // 根据blockHash查询Block信息
              this.$web3.eth.getBlock(blockHash).then(blockObj => {
                console.log(`查询blockHash ${blockHash} 的交易信息结果`, JSON.stringify(blockObj))

                receiptData.timestamp = blockObj.timestamp
                // unshift 向数组的开头添加一个或更多元素
                db.get('trans_logs').unshift(receiptData).write()

                const h = this.$createElement;
                this.$notify({
                  message: h('p', null, [
                    h('p', null, '交易成功！'),
                    h('p', {class: {'success-hash':true}}, `[transactionHash] ${transactionHash}`),
                    h('p', {class: {'success-hash':true}}, `[blockHash] ${blockHash}`),
                  ]),
                  type: 'success',
                  duration: 0,
                  offset: 50
                });

                this.dialogVisible.transaction = false
                this.reloadUsers()
                this.updateBalance(this.transferInfo.from_address)
              })
            })
          })
        } catch (e) {
          console.log('signTransaction失败', e)
          this.$message.error('交易失败')
          return
        }

      },

      // 重置表单
      resetForm () {
        this.$confirm('确认重置表单？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'info'
        }).then(() => {
          this.transferInfo = {
            from_address: '',
            to_address: '',
            amount: 0,
            feePercent: 100,
            extraData: '',
            // user infos
            balance: NaN,
            keystore: {},
            password: ''
          }
        }).catch(() => {
          // 取消操作
        });


      },
      feeTooltip (val) {
        return `${val}%`
      }
    }
  }
</script>

<style lang="stylus" scoped>
.page-transfer
  max-width 550px
  margin 0 auto
  padding: 38px 0 20px;
  .inline-form-items
    display flex
    .money-input
      width 50%
    .text
      padding 0 10px
  .transfer-tips
    margin-bottom: 20px
    &>span
      display inline-block
      background #e6e6e6
      padding 5px
      box-sizing border-box
      border-radius 5px
    &>span+span
      margin-left: 10px
.success-hash
  color: #f00
  word-wrap: break-word;
  max-width: 272px;
  font-family Consolas;
</style>